package com.songqi.common.core.utils;


import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.bean.copier.CopyOptions;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.songqi.common.core.domain.page.PageDataInfo;
import lombok.extern.slf4j.Slf4j;

import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.List;

/**
 * @author songqi(13776346982)
 */
@Slf4j
public class BeanCopyUtil {



    /**
     * 复制bean属性
     * @param source 来源对象
     * @param target 目标对象
     * @throws IllegalAccessException
     * @throws InvocationTargetException
     */
    public static void copyProperties(Object source, Object target) {
        if (source == null) {
            return;
        }
        BeanUtil.copyProperties(source,target);
    }

    /**
     * <p>Description:复制 bean属性</p>
     *
     * @param source 来源对象
     * @param target 目标class对象
     * @return 目标对象
     * @throws IllegalAccessException
     * @throws InvocationTargetException
     * @throws InstantiationException
     */
    public static <T> T copyProperties(Object source, Class<T> target){
        T t = null;
        try {
            t = target.newInstance();
        } catch (Throwable e) {
            log.error("CopyProperties error: {}", e.getMessage(), e);
        }
        if(source == null){
            return null;
        }
        copyProperties(source, t);
        return t;
    }

    /**
     * 将源POJO对象数据复制给目标POJO对象的同名属性
     *
     * @date 2019-1-29
     * @param source 源
     * @param target 目标
     * @param ignoreProperties 无需转换的属性
     * @param <T>
     * @return 目标
     */
    public static <T> T copyProperties(Object source, Class<T> target, String... ignoreProperties) {
        T t = null;
        try{
            t = target.newInstance();
        } catch (Throwable e){
            log.error("Copy Properties error: {}", e.getMessage(), e);
        }
        if(source == null){
            return null;
        }
        BeanUtil.copyProperties(source, t, ignoreProperties);
        return t;
    }


    /**
     * 将源POJO对象数据复制给目标POJO对象的同名属性
     *
     * @date 2019-1-29
     * @param source 源
     * @param target 目标
     * @param ignoreNullProperties 是否无视null值字段（如果为true则无视）
     * @param <T>
     * @return 目标
     */
    public static <T> T copyProperties(Object source, Class<T> target, boolean ignoreNullProperties) {
        T t = null;
        try{
            t = target.newInstance();
        } catch (Throwable e){
            log.error("Copy Properties error: {}", e.getMessage(), e);
        }
        if(source == null){
            return null;
        }
        BeanUtil.copyProperties(source, t, CopyOptions.create().setIgnoreNullValue(ignoreNullProperties));
        return t;
    }

    /**
     * 对象List复制
     *
     * @param ss
     * @param cls
     * @param <S>
     * @param <T>
     * @return
     */
    public static <S, T> List<T> copyList(List<S> ss, Class<T> cls) {

        List<T> tRes = new ArrayList<>();
        if(ss == null || ss.isEmpty()){
            return tRes;
        }
        try {
            for (S s : ss) {
                T t = cls.newInstance();
                BeanUtil.copyProperties(s, t);
                tRes.add(t);
            }
        } catch (Exception e) {
            log.info("类型转换异常，异常信息: ", e);
        }

        return tRes;
    }


    /**
     * 对象List复制
     *
     * @param ss
     * @param cls
     * @param ignoreProperties
     * @param <S>
     * @param <T>
     * @return
     */
    public static <S, T> List<T> copyList(List<S> ss, Class<T> cls, String... ignoreProperties) {

        List<T> tRes = new ArrayList<>();
        if(ss == null || ss.isEmpty()){
            return tRes;
        }
        try {
            for (S s : ss) {
                T t = cls.newInstance();
                BeanUtil.copyProperties(s, t, ignoreProperties);
                tRes.add(t);
            }
        } catch (Exception e) {
            log.info("类型转换异常，异常信息: ", e);
        }

        return tRes;
    }

    /**
     * 对象List复制
     *
     * @param ss
     * @param cls
     * @param ignoreNullProperties
     * @param <S>
     * @param <T>
     * @return
     */
    public static <S, T> List<T> copyList(List<S> ss, Class<T> cls, boolean ignoreNullProperties) {

        List<T> tRes = new ArrayList<>();
        if(ss == null || ss.isEmpty()){
            return tRes;
        }
        try {
            for (S s : ss) {
                T t = cls.newInstance();
                BeanUtil.copyProperties(s, t, CopyOptions.create().setIgnoreNullValue(ignoreNullProperties));
                tRes.add(t);
            }
        } catch (Exception e) {
            log.info("类型转换异常，异常信息: ", e);
        }

        return tRes;

    }


    public static <T, V> PageDataInfo<T> copyProperties(IPage<V> sources, Class<T> targetClsType){
        PageDataInfo<T> t = new PageDataInfo<>();
        t.setTotal(sources.getTotal());
        t.setPageNum(sources.getCurrent());
        t.setMaxPage(sources.getPages());
        t.setPageSize(sources.getSize());
        List<T> targetList = new ArrayList<>();
        List<V> sourceList = sources.getRecords();
        for (V obj : sourceList) {
            targetList.add(copyProperties(obj, targetClsType));
        }
        t.setRows(targetList);
        return t;
    }

    public static <T, V> PageDataInfo<T> copyProperties(PageDataInfo<V> sources, Class<T> targetClsType){
        PageDataInfo<T> t = new PageDataInfo<>();
        t.setTotal(sources.getTotal());
        t.setPageNum(sources.getPageNum());
        t.setMaxPage(sources.getMaxPage());
        t.setPageSize(sources.getPageSize());
        List<T> targetList = new ArrayList<>();
        List<V> sourceList = sources.getRows();
        for (V obj : sourceList) {
            targetList.add(copyProperties(obj, targetClsType));
        }
        t.setRows(targetList);
        return t;
    }
}
